home *** CD-ROM | disk | FTP | other *** search
/ Aminet 31 / Aminet 31 (1999)(Schatztruhe)[!][Jun 1999].iso / Aminet / dev / cross / z88dk_v1.0s.lha / src / copt_win / copt.c next >
Encoding:
C/C++ Source or Header  |  1999-03-20  |  4.9 KB  |  244 lines

  1. /* copt version 1.00 (C) Copyright Christopher W. Fraser 1984 */
  2. /* Added out of memory checking and ANSI prototyping. DG 1999 */
  3.  
  4. #include <ctype.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8.  
  9. #define HSIZE 107
  10. #define MAXLINE 100
  11.  
  12. int debug = 0;
  13.  
  14. struct lnode {
  15.     char *l_text;
  16.     struct lnode *l_prev, *l_next;
  17. };
  18.  
  19. struct onode {
  20.     struct lnode *o_old, *o_new;
  21.     struct onode *o_next;
  22. } *opts = 0;
  23.  
  24. /* error - report error and quit */
  25. void error(char *s)
  26. {
  27.     fputs(s, stderr);
  28.     exit(1);
  29. }
  30.  
  31. /* connect - connect p1 to p2 */
  32. void connect(struct lnode *p1, struct lnode *p2)
  33. {
  34.     if (p1 == 0 || p2 == 0)
  35.         error("connect: can't happen\n");
  36.     p1->l_next = p2;
  37.     p2->l_prev = p1;
  38. }
  39.  
  40. /* install - install str in string table */
  41. char *install(char *str)
  42. {
  43.     register struct hnode *p;
  44.     register char *p1, *p2, *s;
  45.     register int i;
  46.     static struct hnode {
  47.         char *h_str;
  48.         struct hnode *h_ptr;          
  49.     } *htab[HSIZE] = {0};
  50.     
  51.     s = str;
  52.     for (i = 0; *s; i += *s++)
  53.         ;
  54.     i %= HSIZE;
  55.  
  56.     for (p = htab[i]; p; p = p->h_ptr) 
  57.         for (p1=str, p2=p->h_str; *p1++ == *p2++; )
  58.             if (p1[-1] == '\0') 
  59.                 return (p->h_str);
  60.  
  61.     p = (struct hnode *) malloc(sizeof *p);
  62.     if(p==NULL)
  63.         error("install 1: out of memory\n");
  64.     p->h_str = (char *) malloc((s-str)+1);
  65.     if(p->h_str==NULL)
  66.         error("install 2: out of memory\n");
  67.     strcpy(p->h_str, str);
  68.     p->h_ptr = htab[i];
  69.     htab[i] = p;
  70.     return (p->h_str);
  71. }
  72.  
  73. /* insert - insert a new node with text s before node p */
  74. void insert(char *s, struct lnode *p)
  75. {
  76.     struct lnode *n;
  77.  
  78.     n = (struct lnode *) malloc(sizeof *n);
  79.     if(n==NULL)
  80.         error("insert: out of memory\n");
  81.     n->l_text = s;
  82.     connect(p->l_prev, n);
  83.     connect(n, p);
  84. }
  85.  
  86. /* getlst - link lines from fp in between p1 and p2 */
  87. void getlst(FILE *fp, char *quit, struct lnode *p1, struct lnode *p2)
  88. {
  89.     char *install(), lin[MAXLINE];
  90.  
  91.     connect(p1, p2);
  92.     while (fgets(lin, MAXLINE, fp) != NULL && strcmp(lin, quit))
  93.         insert(install(lin), p2);
  94. }
  95.  
  96. /* init - read patterns file */
  97. void init(FILE *fp)
  98. {
  99.     struct lnode head, tail;
  100.     struct onode *p, **next;
  101.  
  102.     next = &opts;
  103.     while (*next)
  104.         next = &((*next)->o_next);
  105.     while (!feof(fp)) {
  106.         p = (struct onode *) malloc((unsigned) sizeof(struct onode));
  107.         if(p==NULL)
  108.             error("init: out of memory\n");
  109.         getlst(fp, "=\n", &head, &tail);
  110.         head.l_next->l_prev = 0;
  111.         if (tail.l_prev)
  112.             tail.l_prev->l_next = 0;
  113.         p->o_old = tail.l_prev;
  114.  
  115.         getlst(fp, "\n", &head, &tail);
  116.         tail.l_prev->l_next = 0;
  117.         if (head.l_next)
  118.             head.l_next->l_prev = 0;
  119.         p->o_new = head.l_next;
  120.  
  121.         *next = p;
  122.         next = &p->o_next;
  123.     }
  124.     *next = 0;
  125. }
  126.  
  127. /* match - match ins against pat and set vars */
  128. int match(char *ins, char *pat, char **vars)
  129. {
  130.     char *p, lin[MAXLINE];
  131.  
  132.     while (*ins && *pat)
  133.         if (pat[0] == '%' && isdigit(pat[1])) {
  134.             for (p = lin; *ins && *ins != pat[2];)
  135.                 *p++ = *ins++;
  136.             *p = 0;
  137.             p = install(lin);
  138.             if (vars[pat[1]-'0'] == 0)
  139.                 vars[pat[1]-'0'] = p;
  140.             else if (vars[pat[1]-'0'] != p)
  141.                 return 0;
  142.             pat += 2;
  143.         }
  144.         else if (*pat++ != *ins++)
  145.             return 0;
  146.     return *pat==*ins;
  147. }
  148.  
  149. /* subst - return result of substituting vars into pat */
  150. char *subst(char *pat, char **vars)
  151. {
  152.     char lin[MAXLINE], *s;
  153.     int i;
  154.  
  155.     i = 0;
  156.     for (;;)
  157.         if (pat[0] == '%' && isdigit(pat[1])) {
  158.             for (s = vars[pat[1]-'0']; i < MAXLINE && (lin[i] = *s++); i++)
  159.                 ;
  160.             pat += 2;
  161.         }
  162.         else if (i >= MAXLINE)
  163.             error("line too long\n");
  164.         else if (!(lin[i++] = *pat++))
  165.             return install(lin);
  166. }
  167.  
  168. /* rep - substitute vars into new and replace lines between p1 and p2 */
  169. struct lnode *rep(struct lnode *p1, struct lnode *p2, struct lnode *new, char **vars)
  170. {
  171.     char *args[10], *exec(), *subst(); 
  172.     int i;
  173.     struct lnode *p, *psav;
  174.  
  175.     for (p = p1->l_next; p != p2; p = psav) {
  176.         psav = p->l_next;
  177.         if (debug)
  178.             fputs(p->l_text, stderr);
  179.         free(p);
  180.     }
  181.     connect(p1, p2);
  182.     if (debug)
  183.         fputs("=\n", stderr);
  184.     for (; new; new = new->l_next) {
  185.         for (i = 0; i < 10; i++)
  186.             args[i] = 0;
  187.         insert(subst(new->l_text, vars), p2);
  188.         if (debug)
  189.             fputs(p2->l_prev->l_text, stderr);
  190.     }
  191.     if (debug)
  192.         putc('\n', stderr);
  193.     return p1->l_next;
  194. }
  195.  
  196. /* opt - replace instructions ending at r if possible */
  197. struct lnode *opt(struct lnode *r)
  198. {
  199.     char *vars[10];
  200.     int i;
  201.     struct lnode *c, *p, *rep();
  202.     struct onode *o;
  203.  
  204.     for (o = opts; o; o = o->o_next) {
  205.         c = r;
  206.         p = o->o_old;
  207.         for (i = 0; i < 10; i++)
  208.             vars[i] = 0;
  209.         while (p && c && match(c->l_text, p->l_text, vars)) {
  210.             p = p->l_prev;
  211.             c = c->l_prev;
  212.         }
  213.         if (p == 0)
  214.             return rep(c, r->l_next, o->o_new, vars);
  215.     }
  216.     return r->l_next;
  217. }
  218.  
  219. /* main - peephole optimizer */
  220. main(int argc, char **argv)
  221. {
  222.     FILE *fp;
  223.     int i;
  224.     struct lnode head, *p, *opt(), tail;
  225.  
  226.     for (i = 1; i < argc; i++)
  227.         if (strcmp(argv[i], "-D") == 0)
  228.             debug = 1;
  229.         else if ((fp=fopen(argv[i], "r")) == NULL) 
  230.             error("copt: can't open patterns file\n");
  231.         else
  232.             init(fp);
  233.  
  234.     getlst(stdin, "", &head, &tail);
  235.     head.l_text = tail.l_text = "";
  236.  
  237.     for (p = head.l_next; p != &tail; p = opt(p))
  238.         ;
  239.  
  240.     for (p = head.l_next; p != &tail; p = p->l_next)
  241.         fputs(p->l_text, stdout);
  242.     exit (0);
  243. }
  244.